import CryptoJS from 'crypto-js'
/***
 * 加解密处理
 * @param {String}   now
 * @param {String}   lessonStartTime
 */
export class Aes {
  constructor (keySize = 128, iterationCount = 8, iv = '', key = '1frvhjgiao82ojce') {
    this.iv = iv
    this.key = CryptoJS.enc.Utf8.parse(key)
    this.keySize = keySize
    this.iterationCount = iterationCount
    this.salt = ''
    this.passPhrase = ''
  }

  setNewKey (iv, key) {
    return new Promise((resolve, reject) => {
      if (iv && key) {
        this.iv = iv
        this.key = key
        resolve(this.iv, this.key)
      } else {
        reject(new Error())
      }
    })
  }

  objPipe (obj, type, props) {
    const result = objCopy(obj)
    props.forEach((prop) => {
      type > 0 ? result[prop] = this.encrypt(obj[prop]) : result[prop] = this.decrypt(obj[prop])
    })

    function objCopy (obj) {
      const copy = {}
      for (const prop in obj) {
        const typeOf = Object.prototype.toString.call(obj[prop])
        if (typeOf === '[object Object]' || typeOf === '[object Array]') {
          objCopy(obj[prop])
        } else {
          copy[prop] = obj[prop]
        }
      }
      return copy
    }
    return result
  }

  encrypt (data, props) {
    const typeOf = Object.prototype.toString.call(data)
    let result = null
    switch (typeOf) {
      case '[object Object]':
        props ? result = this.objPipe(data, 1, props) : result = this.doEncrypt(JSON.stringify(data))
        break
      case '[object Array]':
        props ? result = data.map(e => this.objPipe(e, 1, props)) : result = this.doEncrypt(JSON.stringify(data))
        break
      case '[object String]':
        result = this.doEncrypt(data)
        break
      case '[object Number]':
        result = this.doEncrypt(String(data))
        break
    }
    return result || console.log('加密出错了')
  }

  decrypt (data, props) {
    const typeOf = Object.prototype.toString.call(data)
    let result = null
    switch (typeOf) {
      case '[object Object]':
        props ? result = this.objPipe(data, 0, props) : result = this.doDecrypt(JSON.stringify(data))
        break
      case '[object Array]':
        props ? result = data.map(e => this.objPipe(e, 0, props)) : result = this.doDecrypt(JSON.stringify(data))
        break
      case '[object String]':
        result = this.doDecrypt(data)
        break
      case '[object Number]':
        result = this.doDecrypt(String(data))
        break
    }
    return result || console.log('解密出错了')
  }

  generateKey (salt, passPhrase) {
    const key = CryptoJS.PBKDF2(
      passPhrase,
      CryptoJS.enc.Hex.parse(salt), {
        keySize: this.keySize,
        iterations: this.iterationCount
      })
    this.key = key
  }

  doEncrypt (plainText) {
    const encrypted = CryptoJS.AES.encrypt(
      plainText,
      this.key, {
        iv: CryptoJS.enc.Latin1.parse(this.iv),
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      })
    return encrypted.ciphertext.toString(CryptoJS.enc.Base64)
  }

  doDecrypt (cipherText) {
    // this.generateKey(this.salt, this.passPhrase)
    const decrypted = CryptoJS.AES.decrypt(
      cipherText,
      this.key, {
        iv: CryptoJS.enc.Latin1.parse(this.iv),
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      })
    return decrypted.toString(CryptoJS.enc.Utf8)
  }
}
